檔案結構:
pages/
auth.dart //登入頁
product_create.dart //管理者的新增商品頁
product_list.dart //管理者的商品列表
product.dart //商品細節
product_admin.dart //管理者頁面(有tab那頁)
products.dart //用戶的商品列表
widgets/
products/
address_tag.dart //地址標籤
price_tag.dart //價格標籤
product_card.dart //商品卡
products.dart //如果商品陣列大於零,就呼叫ListView.builder的那個列表
ui_elements/
title_default.dart //字體為Oswald的text
...
routes: {
'/': (BuildContext context) => AuthPage(),
'/products': (BuildContext context) => ProductsPage(_products),
'/admin': (BuildContext context) =>
ProductsAdminPage(_addProduct, _deleteProduct),
},
onGenerateRoute: (RouteSettings settings) {
final List<String> pathElements = settings.name.split('/');
if (pathElements[0] != '') {
return null;
}
if (pathElements[1] == 'product') {
final int index = int.parse(pathElements[2]);
return MaterialPageRoute<bool>(
builder: (BuildContext context) => ProductPage(
_products[index]['title'],
_products[index]['image'],
_products[index]['price'],
_products[index]['description']),
);
}
return null;
},
onUnknownRoute: (RouteSettings settings) {
return MaterialPageRoute(
builder: (BuildContext context) => ProductsPage(_products));
},
...
//把組建拆成function
Widget _buildEmailTextField() {
return TextField(
decoration: InputDecoration(
labelText: 'E-Mail', filled: true, fillColor: Colors.white),
keyboardType: TextInputType.emailAddress,
onChanged: (String value) {
setState(() {
_emailValue = value;
});
},
);
}
build的時候看起來就比較簡潔
Widget build(BuildContext context) {
return Scaffold(
...
body: Container(
...
child: Center(
child: SingleChildScrollView(
child: Column(
children: <Widget>[
_buildEmailTextField(),
...
_buildPasswordTextField(),
_buildAcceptSwitch(),
...
],
),
),
),
),
);
}
Widget _buildSideDrawer(BuildContext context) {
return Drawer(...);
}
@override
Widget build(BuildContext context) {
return Scaffold(
drawer: _buildSideDrawer(context),
Widget _buildProductList() {
Widget productCards;
if (products.length > 0) {
productCards = ListView.builder(
itemBuilder: (BuildContext context, int index) =>
ProductCard(products[index], index),
itemCount: products.length,
);
} else {
productCards = Container();
}
return productCards;
}
...
class ProductCard extends StatelessWidget {
final Map<String, dynamic> product;
final int productIndex;
ProductCard(this.product, this.productIndex);
Widget _buildTitlePriceRow() {
return Container(
...
child: Row(
...
children: <Widget>[
TitleDefault(product['title']),
...
PriceTag(product['price'].toString())
],
),
);
}
Widget _buildActionButtons(BuildContext context) {
return ButtonBar(
...
children: <Widget>[
IconButton(...),
IconButton(...)
],
);
}
@override
Widget build(BuildContext context) {
return Card(
child: Column(
children: <Widget>[
Image.asset(product['image']),
_buildTitlePriceRow(),
AddressTag('Union Square, San Francisco'),
_buildActionButtons(context)
],
),
);
;
}
}
Widget build(BuildContext context) {
return Text(
title,
style: TextStyle(
fontSize: 26.0, fontWeight: FontWeight.bold, fontFamily: 'Oswald'),
);
}
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 6.0, vertical: 2.5),
decoration: BoxDecoration(...),
child: Text(
'$$price',
style: TextStyle(color: Colors.white),
),
);
}
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 6.0, vertical: 2.5),
decoration: BoxDecoration(...),
child: Text(address),
);
}
pages/products_admin.dart
一樣把收合式選單拆出去,function叫_buildSideDrawer
pages/products_create.dart
幾乎要寫function,有行為的,都拆出去,讓build裡面盡量簡潔
class _ProductCreatePageState extends State<ProductCreatePage> {
...
Widget _buildTitleTextField() {
return TextField(
decoration: InputDecoration(labelText: 'Product Title'),
onChanged: (String value) {
setState(() {
_titleValue = value;
});
},
);
}
Widget _buildDescriptionTextField() {
return TextField(
maxLines: 4,
decoration: InputDecoration(labelText: 'Product Description'),
onChanged: (String value) {
setState(() {
_descriptionValue = value;
});
},
);
}
Widget _buildPriceTextField() {
return TextField(
keyboardType: TextInputType.number,
decoration: InputDecoration(labelText: 'Product Price'),
onChanged: (String value) {
setState(() {
_priceValue = double.parse(value);
});
},
);
}
void _submitForm() {
final Map<String, dynamic> product = {
'title': _titleValue,
'description': _descriptionValue,
'price': _priceValue,
'image': 'assets/food.jpg'
};
widget.addProduct(product);
Navigator.pushReplacementNamed(context, '/products');
}
@override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.all(10.0),
child: ListView(
children: <Widget>[
_buildTitleTextField(),
_buildDescriptionTextField(),
_buildPriceTextField(),
SizedBox(
height: 10.0,
),
RaisedButton(
child: Text('Save'),
color: Theme.of(context).accentColor,
textColor: Colors.white,
onPressed: _submitForm,
)
],
),
);
}
}